<?php
declare (strict_types = 1);

namespace app\model;

use app\constant\CommonConstant;
use app\constant\ModelConstant;
use app\helpers\UtilHelper;
use Carbon\Carbon;
use think\annotation\model\relation\BelongsTo;
use think\facade\Db;
use think\facade\Queue;
use think\helper\Arr;
use think\helper\Str;
use think\model\relation\HasMany;
use think\Request;

/**
 * @property integer $id
 * @property string $draft_id
 * @property string $shopify_order_id
 * @property string $ip
 * @property string $checkout_id
 * @property string $created_at
 * @property string $email
 * @property string $shop_currency
 * @property string $present_currency
 * @property string $last_order_name
 * @property string $name
 * @property string $note
 * @property string $order_status_url
 * @property string $phone
 * @property array $payment_token
 * @property float $subtotal_present
 * @property float $subtotal_shop
 * @property float $discount_present
 * @property float $discount_shop
 * @property float $total_present
 * @property float $total_shop
 * @property float $tax_present
 * @property float $tax_shop
 * @property float $shipping_price_present
 * @property float $shipping_price_shop
 * @property float $shipping_protection
 * @property float $repurchase_price
 * @property float $actual_money
 * @property string $updated_at
 * @property string $draft_status
 * @property integer $order_type
 * @property integer $order_status
 * @property mixed $discount_codes
 * @property integer $shop_id
 * @property integer $pay_id
 * @property integer $is_paypal_kj 是否快捷支付
 * @property integer $is_updated 是否完成订单前更新草稿订单
 * @property string $trade_no
 * @property string $order_no
 * @property string $error_msg
 * @property string $utc_at
 * @property integer $is_repurchase
 * @property integer $is_completed
 * @property integer $pay_method
 * @property integer $pay_status
 * @property integer $pid
 * @property string $shipping_name
 * @property string $notify_url
 * @property string $card_number
 * @property integer $paypal_method
 * @property string $cn_at
 * @property string $us_at
 * @property string $fbclid
 * @property string $ad_id
 * @property string $campaign_id
 * @property string $adset_id
 * @property string $user_agent
 * @property string $website
 * @property string $fbc_at
 * @property integer $traffic_platform
 * @property ShopsPayment|null $payment
 * @property Address $shippingAddress
 * @property Address $billingAddress
 * @property Shops|null $shop
 * @property integer $is_support_repurchase
 * @property string $pay_method_name_en
 * @property string $pay_method_name
 * @property BelongsTo $parent

 */
class Orders extends BaseModel
{
    protected $dateFormat = 'U';
    protected $field = [
    'draft_id','shopify_order_id','ip','checkout_id',
    'created_at','email','shop_currency','present_currency',
    'last_order_name','discount_codes','name','note',
    'order_status_url','phone','payment_token','subtotal_present',
    'subtotal_shop','discount_present','discount_shop','total_present',
    'total_shop','shipping_price_present','shipping_price_shop','shipping_protection',
    'updated_at','draft_status','order_type','shop_id',
    'pay_id','order_status','trade_no','order_no',
    'error_msg','is_repurchase','is_completed','pay_status',
    'repurchase_price','utc_at','pay_method','is_paypal_kj',
    'is_updated','pid', 'shipping_name','tax_shop',
    'tax_present','card_number','paypal_method', 'actual_money','cn_at','us_at',
    'fbclid','ad_id','campaign_id','adset_id','user_agent','website','traffic_platform',
    'fbc_at',
    ];

    protected $json = ['discount_codes','payment_token'];
    protected $jsonAssoc = true;
    const ORDER_DRAFT = 2;//草稿订单
    const ORDER_NORMAL = 1;//正常订单
    const ORDER_STATUS_WAIT = 0;//待支付
    const ORDER_STATUS_COMPLETED = 1;//已完成
    const ORDER_STATUS_FAIL = 2;//失败
    const IS_PAYPAL_KJ_Y = 1;//快捷支付是
    const IS_PAYPAL_KJ_N = 0;//快捷支付否
    const PAYPAL_METHOD_GOOGLE = 1;
    const PAYPAL_METHOD_APPLE = 2;

    public static $orderStatus = [
        self::ORDER_STATUS_WAIT => '待支付',
        self::ORDER_STATUS_COMPLETED => '支付成功',
        self::ORDER_STATUS_FAIL => '支付失败',
    ];

    protected $append = [
        'is_support_repurchase','order_status_name',
    ];

    const EXTRA_MONEY = 9.9;

    public function addresses()
    {
        return $this->hasMany(Address::class,'order_id');
    }

    public function items():HasMany
    {
        return $this->hasMany(LineItems::class,'order_id');
    }

    public function shop()
    {
        return $this->belongsTo(Shops::class,'shop_id');
    }

    public function payment()
    {
        return $this->belongsTo(ShopsPayment::class,'pay_id');
    }

    /**
     * @return Address
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @property string $address1
     */
    public function getShippingAddressAttr() :Address|null
    {
        return $this->addresses()->where('type',Address::SHIPPING_ADDRESS)->find();
    }

    public function getBillingAddressAttr():Address|null
    {
        return $this->addresses()->where('type',Address::BILLING_ADDRESS)->find();
    }

    public function getShopAttr():Shops|null
    {
        return $this->shop()->find();
    }


    public function getPaymentAttr(): ShopsPayment|null
    {
        return $this->payment()->find();
    }

    public function getNotifyUrlAttr(): string
    {
        $path = 'api/v1/notify';
        $host = domain(env('APP_HOST'));
        $channel = $this->pay_method_name_en;
        return  sprintf('%s/%s/%s',$host,$path,$channel);
    }

    public function getPayMethodNameEnAttr():string
    {
        return ShopsPayment::$payMethodNames[$this->pay_method] ?? "Paypal";
    }

    public  static function getContextApplicationUrl(Orders $order,Request $request)
    {
        $path = 'api/v1/checkout';
        $host = domain(env('APP_HOST'));
        $referer = $request->header('referer');
        $urlParams = [];
        if($referer){
            $refererList = explode('?', $referer);
            $queryStr = Arr::last($refererList);
            parse_str($queryStr, $urlParams);
        }
        if($order->is_paypal_kj){
           $loadingPath = sprintf("a/s/checkout/%s/credit-card-3ds-redirect-loading",$order->checkout_id);
           $checkout = $request->param('checkout',[]);
           $items = Arr::get($checkout,'cart.items',[]);
           $item = Arr::first($items);
           $url = Arr::get($item,'url','') ?: "/";
           $return_path = Str::contains($referer,"/a/s/checkout") ? sprintf("a/s/checkout/%s/entry",$order->checkout_id) : $url;
        }else {
          $loadingPath= $request->param('loading_path');
          $return_path = $request->param('return_path');
        }
        if(!Arr::exists($urlParams,'cid'))$urlParams['cid'] = $request->header("x-opc-client-id");
        $urlParams['loading_path'] = $loadingPath;
        $urlParams['return_path'] = $return_path;
        $successParams = $cancelParams = $urlParams;
        $successParams['success'] = 'true';
        $cancelParams['success'] = 'false';
        $returnUrl = sprintf('%s/%s/%s?%s',$host,$path,$order->id,UtilHelper::buildQueryString($successParams));
        $cancelUrl = sprintf('%s/%s/%s?%s',$host,$path,$order->id,UtilHelper::buildQueryString($cancelParams));
        return [$returnUrl,$cancelUrl];
    }

    public function notifies(): HasMany
    {
        return $this->hasMany(Notify::class,'order_id');
    }

    public function getWebhookUrlAttr(): string
    {
        return sprintf("%s/api/webhook",ltrim(domain(env('APP_HOST'))));
    }


    public function logs(): HasMany
    {
        return $this->hasMany(OrderLogs::class,'checkout_id');
    }


    public function getIsSupportRepurchaseAttr()
    {
       if(!$this->shop->is_repurchase) return ModelConstant::STATUS_OFF;//支持加购
       if($this->is_repurchase) return ModelConstant::STATUS_OFF;
       if($this->order_status != self::ORDER_STATUS_COMPLETED) return ModelConstant::STATUS_OFF;
       if($this->is_completed) return ModelConstant::STATUS_OFF;
       return ModelConstant::STATUS_ON;
    }



    //计算总价格
    public static function calculateTotalPrice($total_price)
    {
        $default = config('payment.default');
        $value = config('payment.'.$default.'.value');
        if($default == CommonConstant::PAYMENT_TYPE_FIXED){
            $total_money =  bcadd($value,$total_price,2);
            $tax_price = $value;
        }else{
            $percent = bcadd($value,'1.00',2);
            $total_money =  bcmul($total_price,$percent,2);
            $tax_price = bcmul($total_price,$value,2);
        }

        return [$total_money,$tax_price];
    }

    public static function saveExceptionMessage(Orders $order,$error)
    {
        if($order->order_status != self::ORDER_STATUS_COMPLETED){
            $order->order_status = self::ORDER_STATUS_FAIL;
            $order->order_type = self::ORDER_DRAFT;
        }
        $errors = $order->error_msg;
        $errors .= ',' . $error;
        $order->error_msg = $errors;
        $order->save();
    }


    //计算加购AG
    public static function calculateRepurchase($repurchasePrice)
    {
        $repurchasePercent = config('payment.repurchase.value');//加购比率
        $percent = bcadd($repurchasePercent,'1.00',2);
        $total_money =  bcmul($repurchasePrice,$percent,2);
        $tax_price = bcmul($repurchasePrice,$repurchasePercent,2);
        return [$total_money,$tax_price];
    }

    public function getOrderStatusNameAttr($order_status)
    {
        return self::$orderStatus[$order_status] ?? self::$orderStatus[self::ORDER_STATUS_WAIT];
    }

    /**
     * @param Orders $order
     * @param string $pay_status 支付状态
     * @param string $trade_no 订单号
     * @param string $merchant_no 商户号
     * @return true
     */
    public static function completed(Orders $order,string $pay_status='',string $trade_no='',string $merchant_no=''): bool
    {
        $order->order_status = self::ORDER_STATUS_COMPLETED;
        $order->cn_at = Carbon::now()->tz(CommonConstant::CN_TZ)->toDateTimeString();
        $order->us_at = Carbon::now()->addHours(CommonConstant::US_HOUR)->toDateTimeString();
        $order->order_type = self::ORDER_NORMAL;
        $order->updated_at = Carbon::now()->addHours(CommonConstant::US_HOUR)->toDateTimeString();
        if($trade_no)$order->trade_no = $trade_no;
        if($merchant_no)$order->order_no = $merchant_no;
        if($pay_status)$order->pay_status = $pay_status;
        $order->save();
        if($order->is_repurchase){
            self::update(['repurchase_price'=>$order->subtotal_present],['id'=>$order->pid]);
            self::pushShopifyOrder($order->pid);
        }else{
            self::pushShopifyOrder($order->id,(bool)$order->is_support_repurchase);
        }
        return true;
    }

    public function purchases()
    {
        return $this->hasMany(self::class,'pid');
    }

    public function getPayMethodNameAttr()
    {
        return match ($this->pay_method){
            ShopsPayment::PAY_METHOD_ASIABILL => "AB",
            ShopsPayment::PAY_METHOD_STRIPE => "STR",
            ShopsPayment::PAY_METHOD_DIANDIAN => "DD",
            default => "PP"
        };
    }

    public static function pushShopifyOrder(int $orderId,bool $isLater=false): void
    {
        if($isLater){
            Queue::later(600,\app\queue\CompleteDraftQueue::class,$orderId,"CompleteDraftQueue");
        }else{
            Queue::push(\app\queue\CompleteDraftQueue::class,$orderId,"CompleteDraftQueue");
        }
    }

    public function parent()
    {
        return $this->belongsTo(self::class,'id');
    }



}
